/*
 * Copyright (c) 2014 Cesanta Software Limited
 * All rights reserved
 */

#include "http_server.h"

#define REQUST_GET      0X01
#define REQUST_POST     0X02
#define REQUST_PUT      0X04
#define REQUST_DELETE   0X08
#define REQUST_OPTIONS  0X10
#define REQUST_HEAE     0X20
#define REQUST_TRACE    0X40
#define REQUST_CONNECT  0X80
#define REQUST_ALL      0XFF

typedef struct{
	const char *uri;
	const char method;
	void  (*fun)(struct mg_connection*, struct http_message*);
}RELEVANCE_HANDLER;

typedef struct{
	char UID[32];
	char passWD[256];
	int  status;
	int  sessionID;
	int  bEnableVideo;
	int  bEnableAudio;
	int  bEnableSpeaker;
	char rtsp_URL[128];
}DEVICE_HANDLER;

static const char *s_http_port = "8000";
static struct mg_serve_http_opts s_http_server_opts;
static int sg_http_run = 0;  // 线程运行标志

/*****************************************************************************************************
 *              开始书写回调函数
 * ***************************************************************************************************/
static void mg_serve_http_call(struct mg_connection *nc, struct http_message *hm)
{
    mg_serve_http(nc, hm, s_http_server_opts); /* Serve static content */
}

static void test(struct mg_connection *nc, struct http_message *hm)
{
    char data[1024];
    memset( data, 0, sizeof(data) );
	mg_get_http_var(&hm->body, "data", data, sizeof(data));
    printf("data = %s\n", data );

	mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");
    mg_printf_http_chunk(nc,"test\n" );

	mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
}

/*****************************************************************************************************
 *              结束书写回调函数
 * ***************************************************************************************************/

/*
 * @brief URI和函数对应关系图
 * */
static RELEVANCE_HANDLER relevance_aggregation[] = {
	{ "/"            , REQUST_POST | REQUST_GET , mg_serve_http_call} ,
	{ "/api/v1/test" , REQUST_POST              , test}               ,
};

static int requst_type(struct mg_str method)
{
	if(mg_vcmp(&method, "GET" ) == 0) { 
		return REQUST_GET;
	}else if(mg_vcmp(&method, "POST" ) == 0) {
		return REQUST_POST;
	}else if(mg_vcmp(&method, "PUT" ) == 0) {
		return REQUST_PUT;
	}else if(mg_vcmp(&method, "DELETE" ) == 0) {
		return REQUST_DELETE;
	}else if(mg_vcmp(&method, "OPTIONS" ) == 0) {
		return REQUST_OPTIONS;
	}else if(mg_vcmp(&method, "HEAE" ) == 0) {
		return REQUST_HEAE;
	}else if(mg_vcmp(&method, "TRACE" ) == 0) {
		return REQUST_TRACE;
	}else if(mg_vcmp(&method, "CONNECT" ) == 0) {
		return REQUST_CONNECT;
	}else{
		return 0;
	}
}

/*
 * @brief 根据对应的URI查找执行对应的回调函数
 * */
static void handle_http_requset_call(struct mg_connection *nc, struct http_message *hm,struct mg_serve_http_opts opts)
{
    (void)opts;
    int tackNum = sizeof(  relevance_aggregation)/sizeof(RELEVANCE_HANDLER);
    for(int i=0; i<tackNum; i++ ){
        if (mg_vcmp(&hm->uri, relevance_aggregation[i].uri ) == 0) {
            if( (requst_type(hm->method) & relevance_aggregation[i].method) == 0 ){
                mg_http_send_error(nc, 403, "method err\n");
                break;
            }
            relevance_aggregation[i].fun( nc, hm );
            break;
        }
        if( i == tackNum-1 ){
            mg_http_send_error(nc, 400, "URI Ineffective\n");
            printf("uri err\n");
        }
    }

}

/*
 * @brief mongoose的事件处理回调函数
 * */
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data)
{
	struct http_message *hm = (struct http_message *) ev_data;

	switch (ev) {
		case MG_EV_HTTP_REQUEST:
			handle_http_requset_call(nc, hm, s_http_server_opts);
			break;
		default:
			break;
	}
}

/*
 * @brief http server thread
 * */
void *http_server_thread( void *param ) 
{
    (void)param;
	struct mg_mgr mgr;
	struct mg_connection *nc;
	struct mg_bind_opts bind_opts;
	const char *err_str;
#if MG_ENABLE_SSL
	const char *ssl_cert = NULL;
#endif

	mg_mgr_init(&mgr, NULL);

	/* Use current binary directory as document root */
    s_http_server_opts.document_root = ".";

	/* Set HTTP server options */
	memset(&bind_opts, 0, sizeof(bind_opts));
	bind_opts.error_string = &err_str;
#if MG_ENABLE_SSL
	if (ssl_cert != NULL) {
		bind_opts.ssl_cert = ssl_cert;
	}
#endif
	nc = mg_bind_opt(&mgr, s_http_port, ev_handler, bind_opts);
	if (nc == NULL) {
		fprintf(stderr, "Error starting server on port %s: %s\n", s_http_port,
				*bind_opts.error_string);
		exit(1);
	}

	mg_set_protocol_http_websocket(nc);
	s_http_server_opts.enable_directory_listing = "yes";

	printf("Starting RESTful server on port %s, serving %s\n", s_http_port,
			s_http_server_opts.document_root);

    sg_http_run = 1;
	while( sg_http_run ) {
		mg_mgr_poll(&mgr, 1000);
	}
	mg_mgr_free(&mgr);

    pthread_exit(0);
}

